/*
* Poppy Game Engine - https://pgetemplate.googlecode.com/svn/
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* Copyright (c) 2008 Poppy
*/

#pragma once

#ifdef PSP

#include <pspkernel.h>
#include <pspge.h>
#include <pspdisplay.h>
#include "RendererDefines.h"

namespace PGERenderer
{

	typedef void (*Callback)(int);
	typedef void (*SwapBuffersCallback)(void **display, void **render);
	
	typedef struct SSettings
	{
		SSettings()
		{
			m_pSig = 0;
			m_pFin = 0;
			m_iSignalOffset = 0;
			m_iKernelEventFlag = 0;
			m_iGeCallbackId = 0;
			m_iSwapBuffersBehaviour = PSP_DISPLAY_SETBUF_IMMEDIATE;
		}
		Callback m_pSig;
		Callback m_pFin;
		short m_aSignalHistory[16];
		int m_iSignalOffset;
		int m_iKernelEventFlag;
		int m_iGeCallbackId;
		int m_iSwapBuffersBehaviour;
	} Settings;
	
	typedef struct SDisplayList
	{
		SDisplayList()
		{
			m_pStart = 0;
			m_pCurrent = 0;
		}
		unsigned int* m_pStart;
		unsigned int* m_pCurrent;
	} DisplayList;

	typedef struct SContext
	{
		SContext()
		{
			m_iNearPlane = 0;
			m_iFarPlane = 1;
			m_iDepthOffset = 0;
			m_iFragment2x = 0;
			m_iTextureFunction = 0;
			m_iTextureProjMapMode = 0;
			m_iTextureMapMode = 0;
			m_aSpriteMode[0] = 0;
			m_aSpriteMode[1] = 0;
			m_aSpriteMode[2] = 0;
			m_aSpriteMode[3] = 0;
			m_uClearColor = 0x00ff0000;
			m_uClearDepth = 0xffff;
			m_iTextureMode = 0;
			m_pCurrentVertexBuffer = 0;
			m_pCurrentIndexBuffer = 0;
		}
		int m_iNearPlane;
		int m_iFarPlane;
		int m_iDepthOffset;
		int m_iFragment2x;
		int m_iTextureFunction;
		int m_iTextureProjMapMode;
		int m_iTextureMapMode;
		int m_aSpriteMode[4];
		unsigned int m_uClearColor;
		unsigned int m_uClearDepth;
		int m_iTextureMode;
		LPVERTEX_BUFFER m_pCurrentVertexBuffer;
		LPINDEX_BUFFER m_pCurrentIndexBuffer;
	} Context;
	
	typedef struct CDrawBuffer
	{
		CDrawBuffer()
		{
			m_iPixelSize = 3;
			m_iFrameWidth = 512;
			m_pFrameBuffer = 0;
			m_pDispBuffer = (void*)0x88000;
			m_pDepthBuffer = (void*)0x110000;
			m_iDepthWidth = 512;
			m_iWidth = 480;
			m_iHeight = 272;
		}
		
		int m_iPixelSize;
		int m_iFrameWidth;
		void* m_pFrameBuffer;
		void* m_pDispBuffer;
		void* m_pDepthBuffer;
		int m_iDepthWidth;
		int m_iWidth;
		int m_iHeight;
	} DrawBuffer;
	
	typedef struct
	{
		/* row 0 */

		unsigned char enable;	// Light enable
		unsigned char type;	// Light type
		unsigned char xpos;	// X position
		unsigned char ypos;	// Y position

		/* row 1 */

		unsigned char zpos;	// Z position
		unsigned char xdir;	// X direction
		unsigned char ydir;	// Y direction
		unsigned char zdir;	// Z direction

		/* row 2 */

		unsigned char ambient;	// Ambient color
		unsigned char diffuse;	// Diffuse color
		unsigned char specular;	// Specular color
		unsigned char constant;	// Constant attenuation

		/* row 3 */

		unsigned char linear;	// Linear attenuation
		unsigned char quadratic;// Quadratic attenuation
		unsigned char exponent;	// Light exponent
		unsigned char cutoff;	// Light cutoff
	} LightSettings;
	
	class CGraphicSystemData
	{
	public:
		
		CGraphicSystemData() : m_sContexts(), m_sSettings(), m_sList(), m_sDrawBuffer()
		{
			m_iObjectStackDepth = 0;
			m_pGeEdramAddress = sceGeEdramGetAddr();
			m_iClearArea = 1;
			m_pUseableGeEdramAddress = (void*)((unsigned int)m_pGeEdramAddress + 0x154000);
			m_bIsClear = true;
		}
		
		Context m_sContexts;
		Settings m_sSettings;
		DisplayList m_sList;
		DrawBuffer m_sDrawBuffer;
		LightSettings m_aLightSettings[4];
		void* m_pGeEdramAddress;
		void* m_pUseableGeEdramAddress;
		int* m_aObjectStack[32];
		int m_iObjectStackDepth;
		int m_iGeListExecuted;
		bool m_bIsClear;
		unsigned int m_iClearArea;
	};
	
	inline void SendDictationToData(CGraphicSystemData* data, int dictation)
	{
		*(data->m_sList.m_pCurrent++) = dictation;
	}
	
	inline void SendCommandToDatai(CGraphicSystemData* data, int cmd, int argument)
	{
		SendDictationToData(data, (cmd << 24) | (argument & 0xffffff));
	}
	
	inline void SendCommandToDataf(CGraphicSystemData* data, int cmd, float argument)
	{
		union
		{
			float f;
			unsigned int i;
		} t;
		t.f = argument;
		SendCommandToDatai(data, cmd, t.i >> 8);
	}
	
}

#endif

#ifdef WIN32
#include "CWinInit.h"

namespace PGERenderer
{

	class CGraphicSystemData
	{
	public:

		CGraphicSystemData() : m_cWinInit()
		{
			m_pD3D = NULL;
			m_pD3DDevice = NULL;
			ZeroMemory(&m_sD3DPresentPara, sizeof(D3DPRESENT_PARAMETERS));
			ZeroMemory(&m_sMessage, sizeof(MSG));
			m_iClearArea = PGE_CLEAR_COLOR | PGE_CLEAR_DEPTH | PGE_CLEAR_STENCIL;
			m_uClearColor = 0;
			m_fClearDepth = 1.0f;
			m_uClearStencil = 0;

		}

		CWinInit				m_cWinInit;
		MSG						m_sMessage;
		LPDIRECT3D9				m_pD3D;
		LPDIRECT3DDEVICE9		m_pD3DDevice;
		D3DPRESENT_PARAMETERS	m_sD3DPresentPara;
		unsigned int			m_iClearArea;
		D3DCOLOR				m_uClearColor;
		float					m_fClearDepth;
		DWORD					m_uClearStencil;
		DWORD					m_uVertexSize;
		LPVERTEX_BUFFER			m_pMainVBuffer;
		LPINDEX_BUFFER			m_pMainIBuffer;
		DWORD					m_uVBOffset;
		DWORD					m_uIBOffset;

	};

}

#endif
